﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using AutoMapper;
using DTcms.Core.API.Filters;
using DTcms.Core.Common.Emum;
using DTcms.Core.Common.Extensions;
using DTcms.Core.Common.Helper;
using DTcms.Core.IServices;
using DTcms.Core.Model.Models;
using DTcms.Core.Model.ViewModels;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.JsonPatch;
using Microsoft.AspNetCore.Mvc;

namespace DTcms.Core.API.Controllers
{
    /// <summary>
    /// 文章评论
    /// </summary>
    [Route("article/comment")]
    [ApiController]
    public class ArticleCommentController : ControllerBase
    {
        private readonly IArticleCommentService _commentService;
        private readonly IUserService _userService;
        private readonly IMapper _mapper;
        private readonly IArticleCommentLikeService _likeService;
        private readonly ISiteChannelService _channelService;
        private readonly IArticleService _articleService;

        public ArticleCommentController(IArticleCommentService commentService, IUserService userService, IArticleCommentLikeService likeService, IMapper mapper, ISiteChannelService channelService, IArticleService articleService)
        {
            _commentService = commentService;
            _userService = userService;
            _likeService = likeService;
            _mapper = mapper;
            _articleService = articleService;
            _channelService = channelService;
        }

        /// <summary>
        /// 根据ID获取数据
        /// 示例：/article/comment/1/1
        /// </summary>
        [HttpGet("{channelId}/{id}")]
        [Authorize]
        [AuthorizeFilter("ArticleComment", ActionType.View, "channelId")]
        public async Task<IActionResult> GetById([FromRoute] int id, [FromQuery] BaseParameter param)
        {
            //检测参数是否合法
            if (!param.Fields.IsPropertyExists<ArticleCommentDto>())
            {
                return BadRequest(ResponseMessage.Error("请输入正确的属性参数"));
            }
            //查询数据库获取实体
            var model = await _commentService.QueryAsync(x => x.Id == id);
            if (model == null)
            {
                return NotFound(ResponseMessage.Error($"数据{id}不存在或已删除"));
            }
            //使用AutoMapper转换成ViewModel，根据字段进行塑形
            var result = _mapper.Map<ArticleCommentDto>(model).ShapeData(param.Fields);
            return Ok(result);
        }

        /// <summary>
        /// 获取分页列表
        /// 示例：/article/comment/1?pageSize=10&pageIndex=1
        /// </summary>
        [HttpGet("{channelId}")]
        [Authorize]
        [AuthorizeFilter("ArticleComment", ActionType.View, "channelId")]
        public async Task<IActionResult> GetList([FromRoute] int channelId, [FromQuery] BaseParameter searchParam, [FromQuery] PageParamater pageParam)
        {
            //检测参数是否合法
            if (searchParam.OrderBy.IsNotNullOrEmpty()
                && !searchParam.OrderBy.Replace("-", "").IsPropertyExists<ArticleCommentDto>())
            {
                return BadRequest(ResponseMessage.Error("请输入正确的排序参数"));
            }
            if (!searchParam.Fields.IsPropertyExists<ArticleCommentDto>())
            {
                return BadRequest(ResponseMessage.Error("请输入正确的属性参数"));
            }

            //获取数据列表，如果ID大于0则查询该用户下所有的列表
            var list = await _commentService.QueryPageAsync(
                pageParam.PageSize,
                pageParam.PageIndex,
                x => searchParam.Keyword.IsNotNullOrEmpty() ? x.Content.Contains(searchParam.Keyword) && x.ChannelId == channelId : true && x.ChannelId == channelId,
                searchParam.OrderBy.IsNotNullOrWhiteSpace() ? searchParam.OrderBy : "AddTime,-Id");
            if (list == null || list.Count() <= 0)
            {
                return NotFound(ResponseMessage.Error("暂无查询到记录"));
            }

            //x-pagination
            var paginationMetadata = new
            {
                totalCount = list.TotalCount,
                pageSize = list.PageSize,
                pageIndex = list.PageIndex,
                totalPages = list.TotalPages
            };
            Response.Headers.Add("x-pagination", SerializeHelper.SerializeObject(paginationMetadata));

            //映射成DTO，根据字段进行塑形
            var resultDto = _mapper.Map<IEnumerable<ArticleCommentDto>>(list).ShapeData(searchParam.Fields);
            return Ok(resultDto);
        }

        /// <summary>
        /// 修改一条记录
        /// 示例：/ArticleComment/1/1
        /// </summary>
        [HttpPut("{channelId}/{id}")]
        [Authorize]
        [AuthorizeFilter("ArticleComment", ActionType.Edit, "channelId")]
        public async Task<IActionResult> Update([FromRoute] long id, [FromBody] ArticleCommentAddDto modelDto)
        {
            //查找记录
            var model = await _commentService.QueryAsync<ArticleComment>(x => x.Id == id, WriteRoRead.Write);
            if (model == null)
            {
                return NotFound(ResponseMessage.Error($"数据{id}不存在或已删除"));
            }

            //更新操作AutoMapper替我们完成，只需要调用保存即可
            _mapper.Map(modelDto, model);
            var result = await _commentService.SaveAsync();
            return NoContent();
        }

        /// <summary>
        /// 批量审核
        /// 示例：/ArticleComment/1?ids=
        /// </summary>
        [HttpPut("{channelId}")]
        [Authorize]
        [AuthorizeFilter("ArticleComment", ActionType.Audit, "channelId")]
        public async Task<IActionResult> Updates([FromRoute] int channelId, [FromQuery] string ids)
        {
            if (string.IsNullOrWhiteSpace(ids))
            {
                return NotFound(ResponseMessage.Error($"请先选择数据"));
            }
            var idsArr = ids.ToIEnumerable<long>();
            //查找记录
            var list = await _commentService.QueryListAsync<ArticleComment>(0, t => idsArr.Contains(t.Id) && t.ChannelId == channelId);
            if (list == null)
            {
                return NotFound(ResponseMessage.Error($"没有要修改的对象"));
            }
            else
            {
                foreach (var item in list)
                {
                    item.Status = 0;
                }
                var result = await _commentService.UpdateAsync(list, WriteRoRead.Write);
            }
            return NoContent();
        }

        /// <summary>
        /// 删除一条记录
        /// 示例：/article/comment/1/1
        /// </summary>
        [HttpDelete("{channelId}/{id}")]
        [Authorize]
        [AuthorizeFilter("ArticleComment", ActionType.Delete, "channelId")]
        public async Task<IActionResult> Delete([FromRoute] int id, [FromRoute] int channelId)
        {
            if (!await _commentService.ExistsAsync<ArticleComment>(x => x.Id == id))
            {
                return NotFound(ResponseMessage.Error($"数据{id}不存在或已删除"));
            }
            var result = await _commentService.DeleteAsync<ArticleComment>(x => x.Id == id && x.ChannelId == channelId);

            return NoContent();
        }

        /// <summary>
        /// 批量删除记录(级联数据)
        /// 示例：/article/comment/1?ids=1,2,3
        /// </summary>
        [HttpDelete("{channelId}")]
        [Authorize]
        [AuthorizeFilter("ArticleComment", ActionType.Delete, "channelId")]
        public async Task<IActionResult> DeleteByIds([FromRoute] int channelId, [FromQuery] string Ids)
        {
            if (Ids == null)
            {
                return BadRequest(ResponseMessage.Error("传输参数不可为空"));
            }
            //将ID列表转换成IEnumerable
            var idList = Ids.ToIEnumerable<long>();
            if (idList == null)
            {
                return BadRequest(ResponseMessage.Error("传输参数不符合规范"));
            }
            //执行批量删除操作
            await _commentService.DeleteAsync<ArticleComment>(x => idList.Contains(x.Id) && x.ChannelId == channelId);

            return NoContent();
        }

        /// <summary>
        /// 软删除一条记录
        /// 示例：/article/comment/mark/1/1
        /// </summary>
        [HttpPut("mark/{channelId}/{id}")]
        [Authorize]
        [AuthorizeFilter("ArticleComment", ActionType.Delete, "channelId")]
        public async Task<IActionResult> MarkDelete([FromRoute] int id, [FromRoute] int channelId)
        {
            if (!await _commentService.ExistsAsync<ArticleComment>(x => x.Id == id))
            {
                return NotFound(ResponseMessage.Error($"数据{id}不存在或已删除"));
            }
            var result = await _commentService.MarkDeleteAsync(x => x.Id == id && x.ChannelId == channelId);

            return NoContent();
        }

        /// <summary>
        /// 批量软删除记录(级联数据)
        /// 示例：/article/comment/mark/1?ids=1,2,3
        /// </summary>
        [HttpPut("mark/{channelId}")]
        [Authorize]
        [AuthorizeFilter("ArticleComment", ActionType.Delete, "channelId")]
        public async Task<IActionResult> MarkDeleteByIds([FromRoute] int channelId, [FromQuery] string Ids)
        {
            if (Ids == null)
            {
                return BadRequest(ResponseMessage.Error("传输参数不可为空"));
            }
            //将ID列表转换成IEnumerable
            var idList = Ids.ToIEnumerable<long>();
            if (idList == null)
            {
                return BadRequest(ResponseMessage.Error("传输参数不符合规范"));
            }
            //执行批量删除操作
            await _commentService.MarkDeleteAsync(x => idList.Contains(x.Id) && x.ChannelId == channelId);

            return NoContent();
        }

        #region 前台调用接口============================
        /// <summary>
        /// 获取指定文章评价总数
        /// 示例：/client/article/comment/count/1
        /// </summary>
        [HttpGet("/client/article/comment/count/{articleId}")]
        public async Task<IActionResult> GetByArticleCount([FromRoute] long articleId, [FromQuery] BaseParameter searchParam)
        {
            //检测参数是否合法
            if (searchParam.OrderBy.IsNotNullOrEmpty()
                && !searchParam.OrderBy.Replace("-", "").IsPropertyExists<ArticleCommentDto>())
            {
                return BadRequest(ResponseMessage.Error("请输入正确的排序参数"));
            }

            //获取数据库列表
            var result = await _commentService.QueryCountAsync(
                    x => x.Status == 0
                    && x.ArticleId == articleId
                    && (!searchParam.Keyword.IsNotNullOrEmpty() || x.Content.Contains(searchParam.Keyword))
                    );
            //返回成功200
            return Ok(result);
        }

        /// <summary>
        /// 获取指定文章评价列表
        /// 示例：/client/article/comment/view/1/10
        /// </summary>
        [HttpGet("/client/article/comment/view/{articleId}/{top}")]
        public async Task<IActionResult> GetByArticleList([FromRoute] long articleId, [FromRoute] int top, [FromQuery] BaseParameter searchParam)
        {
            //检测参数是否合法
            if (searchParam.OrderBy.IsNotNullOrEmpty()
                && !searchParam.OrderBy.Replace("-", "").IsPropertyExists<ArticleCommentDto>())
            {
                return BadRequest(ResponseMessage.Error("请输入正确的排序参数"));
            }
            if (!searchParam.Fields.IsPropertyExists<ArticleCommentDto>())
            {
                return BadRequest(ResponseMessage.Error("请输入正确的属性参数"));
            }

            //获取数据库列表
            var resultFrom = await _commentService.QueryListAsync(top,
                    x => x.Status == 0
                    && x.ArticleId == articleId
                    && (!searchParam.Keyword.IsNotNullOrEmpty() || x.Content.Contains(searchParam.Keyword)),
                (searchParam.OrderBy.IsNotNullOrWhiteSpace() ? searchParam.OrderBy : "-Id"));

            //根据字段进行塑形
            var resultDto = resultFrom.ShapeData(searchParam.Fields);
            //返回成功200
            return Ok(resultDto);
        }

        /// <summary>
        /// 获取指定文章评价分页列表
        /// 示例：/client/article/comment/1?pageSize=10&pageIndex=1
        /// </summary>
        [HttpGet("/client/article/comment/{articleId}")]
        public async Task<IActionResult> GetByArticlePageList([FromRoute] long articleId, [FromQuery] BaseParameter param, [FromQuery] PageParamater pageParam)
        {
            param.Fields = "Id,ParentId,RootId,UserName,UserAvatar,AtUserName," +
                "Content,LikeCount,DateDescription,Children";

            //检测参数是否合法
            if (param.OrderBy.IsNotNullOrEmpty()
                && !param.OrderBy.Replace("-", "").IsPropertyExists<ArticleCommentDto>())
            {
                return BadRequest(ResponseMessage.Error("请输入正确的排序参数"));
            }
            if (!param.Fields.IsPropertyExists<ArticleCommentDto>())
            {
                return BadRequest(ResponseMessage.Error("请输入正确的属性参数"));
            }

            //获取数据列表，如果ID大于0则查询该用户下所有的列表
            var list = await _commentService.QueryPageFromDtoAsync(
                pageParam.PageSize,
                pageParam.PageIndex,
                 x => x.Status == 0 && x.ArticleId == articleId
                    && (!param.Keyword.IsNotNullOrEmpty() || x.Content.Contains(param.Keyword)),
                param.OrderBy.IsNotNullOrWhiteSpace() ? param.OrderBy : "-Id");
            if (list == null || list.Count() <= 0)
            {
                return NotFound(ResponseMessage.Error("暂无查询到记录"));
            }

            //x-pagination
            var paginationMetadata = new
            {
                totalCount = list.TotalCount,
                pageSize = list.PageSize,
                pageIndex = list.PageIndex,
                totalPages = list.TotalPages
            };
            Response.Headers.Add("x-pagination", SerializeHelper.SerializeObject(paginationMetadata));

            //根据字段进行塑形
            var resultDto = list.AsEnumerable().ShapeData(param.Fields);
            return Ok(resultDto);
        }

        /// <summary>
        /// 添加一条记录
        /// 示例：/client/article/comment/add
        /// </summary>
        [Authorize]
        [HttpPost("/client/article/comment/add")]
        public async Task<IActionResult> Add([FromBody] ArticleCommentAddDto modelDto)
        {
            if (modelDto.SiteId <= 0)
            {
                return BadRequest(ResponseMessage.Error("请输入正确的属性参数"));
            }
            //获取文章实体
            var articleModel = await _articleService.QueryAsync(t => t.Id == modelDto.ArticleId);
            if (articleModel == null)
            {
                return BadRequest(ResponseMessage.Error("请输入正确的属性参数"));
            }
            //判断是否关闭评论
            if (articleModel.IsComment == 0 || articleModel.SiteChannel.IsComment == 0)
            {

                return BadRequest(ResponseMessage.Error("评论已经关闭！"));
            }

            modelDto.UserIp = HttpContext.Connection.RemoteIpAddress.ToString();
            //写入数据库
            var mapModel = await _commentService.AddAsync(modelDto);
            //映射成DTO再返回，否则出错
            var result = _mapper.Map<ArticleCommentDto>(mapModel);
            var model = new
            {
                Id = result.Id,
                ParentId = result.ParentId,
                RootId = result.RootId,
                UserName = result.UserName,
                UserAvatar = result.UserAvatar,
                AtUserName = result.AtUserName,
                Content = result.Content,
                LikeCount = result.LikeCount,
                DateDescription = result.DateDescription,
                Children = result.Children,
            };
            return Ok(model);
        }

        /// <summary>
        /// 更新点赞量
        /// 示例：/client/article/comment/like/1
        /// </summary>
        [Authorize]
        [HttpPut("/client/article/comment/like/{commentId}")]
        public async Task<IActionResult> UpdateLike([FromRoute] long commentId)
        {
            long likeCount = 0;
            likeCount = await _likeService.UserUpdateLikeAsync(commentId);
            return Ok(likeCount);

        }
        #endregion
    }
}
